package com.cunzhang.common.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecurityException;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.InvalidKeyException;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.Map;

/**
 * JWT 工具类
 * 兼容 JJWT 0.12.5+ 版本
 */
public class JwtUtil {

    /**
     * 生成JWT Token
     * @param secretKey 密钥字符串
     * @param ttlMillis 过期时间(毫秒)
     * @param claims 自定义claims
     * @return JWT Token字符串
     * @throws InvalidKeyException 当密钥不符合要求时抛出
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 1. 将密钥转换为Key对象
        Key key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));

        // 2. 计算过期时间
        long nowMillis = System.currentTimeMillis();
        Date exp = new Date(nowMillis + ttlMillis);

        // 3. 构建JWT
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date(nowMillis))
                .setExpiration(exp)
                .signWith(key)
                .compact();
    }

    /**
     * 解析JWT Token
     * @param secretKey 密钥字符串
     * @param token JWT Token
     * @return Claims对象
     * @throws ExpiredJwtException 当Token过期时抛出
     * @throws UnsupportedJwtException 当Token格式不支持时抛出
     * @throws MalformedJwtException 当Token格式错误时抛出
     * @throws SecurityException 当签名验证失败时抛出
     * @throws IllegalArgumentException 当Token为null或空时抛出
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 1. 将密钥转换为Key对象
        Key key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));

        // 2. 解析Token
        return Jwts.parser()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 验证JWT Token是否有效
     * @param secretKey 密钥字符串
     * @param token JWT Token
     * @return 是否有效
     */
    public static boolean validateToken(String secretKey, String token) {
        try {
            parseJWT(secretKey, token);
            return true;
        } catch (SecurityException e) {
            // 签名验证失败
        } catch (MalformedJwtException e) {
            // JWT格式错误
        } catch (ExpiredJwtException e) {
            // JWT已过期
        } catch (UnsupportedJwtException e) {
            // 不支持的JWT类型
        } catch (IllegalArgumentException e) {
            // 参数错误
        }
        return false;
    }

    /**
     * 生成安全的随机密钥(Base64编码)
     * @return 安全的随机密钥字符串
     */
    public static String generateSecureRandomKey() {
        return Encoders.BASE64.encode(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
    }

    /**
     * 从Base64编码的密钥字符串创建Key对象
     * @param base64Key Base64编码的密钥
     * @return Key对象
     */
    public static Key getKeyFromBase64(String base64Key) {
        byte[] keyBytes = Decoders.BASE64.decode(base64Key);
        return Keys.hmacShaKeyFor(keyBytes);
    }
}